package enums

import (
	"gitee.com/hongzhaomin/gspring/annotation"
	"gitee.com/hongzhaomin/gspring/consts"
	"gitee.com/hongzhaomin/gspring/tools"
	"reflect"
)

var (
	rtGspringBean         = new(annotation.Component).GetRtGspringBean()
	rtConfigurationAnno   = new(annotation.Configuration).GetRtConfigurationAnno()
	rtScanStructFieldAnno = new(annotation.ScanStructField).GetRtScanStructFieldAnno()
)

type BeanKind uint

func (bk BeanKind) String() string {
	switch bk {
	case Bean:
		return rtGspringBean.Name()
	case Configuration:
		return rtConfigurationAnno.Name()
	case ScanStructField:
		return rtScanStructFieldAnno.Name()
	default:
		return ""
	}
}

func (bk BeanKind) Is(kind BeanKind) bool {
	return bk == kind
}

func (bk BeanKind) IsValid() bool {
	return !Invalid.Is(bk)
}

func (bk BeanKind) ResolveBeanName(refType reflect.Type) string {
	var beanName string
	switch bk {
	case Bean:
		beanName, _ = tools.FindAnnotationValueByType(refType, (*annotation.Component)(nil), consts.GspringBeanNameTag)
	case Configuration:
		beanName, _ = tools.FindAnnotationValueByType(refType, (*annotation.Configuration)(nil), consts.GspringBeanNameTag)
	case ScanStructField:
		beanName, _ = tools.FindAnnotationValueByType(refType, (*annotation.ScanStructField)(nil), consts.GspringBeanNameTag)
	default:
		// nothing to do
	}
	if beanName != "" {
		return beanName
	}
	return tools.GetBeanName(refType.Name())
}

func (bk BeanKind) GetBeanType() any {
	switch bk {
	case Bean:
		return (*annotation.Component)(nil)
	case Configuration:
		return (*annotation.Configuration)(nil)
	case ScanStructField:
		return (*annotation.ScanStructField)(nil)
	default:
		return nil
	}
}

const (
	Invalid BeanKind = iota
	Bean
	Configuration
	ScanStructField
)

func GetBeanKindEnum(bean any) BeanKind {
	// 注意：实现了annotation.BeanConfiguration的对象，一定也实现了annotation.GspringBean接口，由于annotation.Configuration的设计
	// 所以这里判断Bean的种类的时候，需要先判断 annotation.RtConfigurationAnno
	//switch bean.(type) {
	//case annotation.configurationAnno:
	//	return Configuration
	//case annotation.gspringBean:
	//	return Bean
	//case annotation.scanStructFieldAnno:
	//	return ScanStructField
	//default:
	//	return Invalid
	//}

	// 为了不引用annotation包中的注解接口，放弃使用以上方法，使用反射的方式进行判断
	return GetBeanKindEnumByType(tools.IndirectReflectType(bean))
}

func GetBeanKindEnumByType(refType reflect.Type) BeanKind {
	// 注意：实现了annotation.BeanConfiguration的对象，一定也实现了annotation.GspringBean接口，由于annotation.Configuration的设计
	// 所以这里判断Bean的种类的时候，需要先判断 annotation.RtConfigurationAnno
	switch {
	case refType.Implements(rtScanStructFieldAnno) ||
		reflect.New(refType).Type().Implements(rtScanStructFieldAnno):
		return ScanStructField
	case refType.Implements(rtConfigurationAnno) ||
		reflect.New(refType).Type().Implements(rtConfigurationAnno):
		return Configuration
	case refType.Implements(rtGspringBean) ||
		reflect.New(refType).Type().Implements(rtGspringBean):
		return Bean
	default:
		return Invalid
	}
}
